import type { BasicTableProps, FetchParams } from '../types/table';
import {
  ref,
  unref,
  type ComputedRef,
  computed,
  onMounted,
  watch,
  reactive,
  type Ref,
  watchEffect,
} from 'vue';
import { useTimeoutFn } from '@vueuse/core';
import {
  get,
  cloneDeep,
  merge,
  isFunction,
  isBoolean,
  has,
  isObject,
  isUndefined,
} from 'lodash-es';
import type { PaginationProps } from 'element-plus';
import { FETCH_SETTING, PAGE_SIZE, ROW_KEY } from '../const';
import type { PaginationPropsType } from '../types/pagination';
import type { Recordable } from '#/types/global';
import { buildUUID } from '#/utils/gloab';

interface ActionType {
  getPaginationInfo: ComputedRef<boolean | PaginationProps | PaginationPropsType>;
  setPagination: (info: Partial<PaginationProps>) => void;
  setLoading: (loading: boolean) => void;
  getFieldsValue: () => Recordable;
  tableData: Ref<Recordable[]>;
}

interface SearchState {
  sortInfo: Recordable;
  filterInfo: Record<string, string[]>;
}
export function useVxeDataSource(
  propsRef: ComputedRef<BasicTableProps>,
  { getPaginationInfo, setPagination, setLoading, getFieldsValue, tableData }: ActionType,
  emit: { (event: string, ...args: any[]): void; (arg0: string, arg1: unknown): void },
) {
  const searchState = reactive<SearchState>({
    sortInfo: {},
    filterInfo: {},
  });
  const dataSourceRef = ref<Recordable[]>([]);
  const rawDataSourceRef = ref<Recordable>({});

  watchEffect(() => {
    tableData.value = unref(dataSourceRef);
  });

  watch(
    () => unref(propsRef).dataSource,
    () => {
      const { dataSource, api } = unref(propsRef);
      if (!api && dataSource) {
        dataSourceRef.value = dataSource;
      }
    },
    {
      immediate: true,
      deep: true,
    },
  );

  function setTableKey(items: any[]) {
    if (!items || !Array.isArray(items)) return;
    items.forEach((item) => {
      if (!item[ROW_KEY]) {
        item[ROW_KEY] = buildUUID();
      }
      if (item.children && item.children.length) {
        setTableKey(item.children);
      }
    });
  }

  const getAutoCreateKey = computed(() => {
    return unref(propsRef).autoCreateKey && !unref(propsRef).rowKeyd;
  });

  const getRowKey = computed(() => {
    const { rowKeyd } = unref(propsRef);
    return unref(getAutoCreateKey) ? ROW_KEY : rowKeyd;
  });
  // 表格数据
  const getDataSourceRef = computed(() => {
    const dataSource = unref(dataSourceRef);
    if (!dataSource || dataSource.length === 0) {
      return unref(dataSourceRef);
    }
    if (unref(getAutoCreateKey)) {
      const firstItem = dataSource[0];
      const lastItem = dataSource[dataSource.length - 1];

      if (firstItem && lastItem) {
        if (!firstItem[ROW_KEY] || !lastItem[ROW_KEY]) {
          const data = cloneDeep(unref(dataSourceRef));
          data.forEach((item) => {
            if (!item[ROW_KEY]) {
              item[ROW_KEY] = buildUUID();
            }
            if (item.children && item.children.length) {
              setTableKey(item.children);
            }
          });
          dataSourceRef.value = data;
        }
      }
    }
    return unref(dataSourceRef);
  });
  // 跟新数据
  async function updateTableData(index: number, key: string, value: any) {
    const record = dataSourceRef.value[index];
    if (record) {
      (dataSourceRef.value as any)[index][key] = value;
    }
    return dataSourceRef.value[index];
  }
  // 获取数据
  async function fetch(opt?: FetchParams): Promise<any> {
    const { api, searchInfo, fetchSetting, beforeFetch, afterFetch, useSearchForm, pagination } =
      unref(propsRef);
    if (!api || !isFunction(api)) return console.warn('api接口不存在');
    try {
      setLoading(true);
      const { pageField, sizeField, listField, totalField } = { ...FETCH_SETTING, ...fetchSetting };
      let pageParams: Recordable = {};
      let currentPage = 1;
      let pageSize = PAGE_SIZE;
      if ((isBoolean(pagination) && !pagination) || isBoolean(getPaginationInfo)) {
        pageParams = {};
      } else {
        const { currentPage: currentPaged, pageSize: pageSized } = unref(
          getPaginationInfo,
        ) as PaginationProps;
        currentPage = currentPaged || 1;
        if (opt && opt.page) {
          currentPage = opt.page;
        }
        pageSize = pageSized || PAGE_SIZE;
        pageParams[pageField] = currentPage;
        pageParams[sizeField] = pageSize;
      }

      const { sortInfo = {}, filterInfo } = searchState;

      let params: Recordable = merge(
        pageParams,
        useSearchForm ? getFieldsValue() : {},
        searchInfo,
        opt?.searchInfo ?? {},
        sortInfo,
        filterInfo,
        opt?.sortInfo ?? {},
        opt?.filterInfo ?? {},
      );
      if (beforeFetch && isFunction(beforeFetch)) {
        params = (await beforeFetch(params)) || params;
      }
      // console.log('params', params);
      const res = await api(params);

      let data = res;
      if (has(res, 'code')) {
        if (res.code != 0) {
          emit('fetch-error', res.data);
          dataSourceRef.value = [];
          setPagination({
            total: 0,
          });
          return;
        }
        data = res.data;
      }

      rawDataSourceRef.value = data;

      const isArrayResult = Array.isArray(data);

      let resultItems: Recordable[] = isArrayResult ? data : get(data, listField);
      const resultTotal: number = isArrayResult ? data.length : get(data, totalField);

      // 假如数据变少，导致总页数变少并小于当前选中页码，通过getPaginationRef获取到的页码是不正确的，需获取正确的页码再次执行
      if (Number(resultTotal)) {
        const currentTotalPage = Math.ceil(resultTotal / pageSize);
        if (currentPage > currentTotalPage) {
          setPagination({
            currentPage: currentTotalPage,
          });
          return await fetch(opt);
        }
      }

      if (afterFetch && isFunction(afterFetch)) {
        resultItems = (await afterFetch(data)) || resultItems;
      }
      dataSourceRef.value = resultItems;
      setPagination({
        total: resultTotal || 0,
      });
      if (opt && opt.page) {
        setPagination({
          currentPage: opt.page,
        });
      }
      emit('fetch-success', {
        items: unref(resultItems),
        total: resultTotal,
      });
      return resultItems;
    } catch (error) {
      emit('fetch-error', error);
      dataSourceRef.value = [];
      setPagination({
        total: 0,
      });
    } finally {
      setLoading(false);
    }
  }

  function setTableData<T extends Ref<Recordable<any>[]>>(values: T[]) {
    dataSourceRef.value = values;
  }
  /**根据唯一的rowKey 动态删除指定行的数据.可用于不刷新整个表格而局部更新数据 */
  function deleteSelectRowByKey(key: string) {
    const selectedRowKeys = unref(dataSourceRef);
    const index = selectedRowKeys.findIndex((item) => item.key === key);
    if (index !== -1) {
      unref(dataSourceRef).splice(index, 1);
    }
  }
  /**可根据传入的 index 值决定插入数据行的位置，不传则是顺序插入，可用于不刷新整个表格而局部更新数据 */
  function insertTableDataRecord(
    record: Recordable | Recordable[],
    index?: number,
  ): Recordable[] | undefined {
    index = isUndefined(index) ? dataSourceRef.value?.length : index;
    const _record = isObject(record) ? [record as Recordable] : (record as Recordable[]);
    unref(dataSourceRef).splice(index, 0, ..._record);
    return unref(dataSourceRef);
  }

  /** 根据唯一的 rowKey 更新指定行的数据.可用于不刷新整个表格而局部更新数据 */
  function updateTableDataRecord(
    rowKey: string | number,
    record: Recordable,
  ): Recordable | undefined {
    const row: any = findTableDataRecord(rowKey);
    if (row) {
      for (const field in row) {
        if (Reflect.has(record, field)) row[field] = record[field];
      }
      return row;
    }
  }
  /**获取 rowKey 指定数据 */
  function findTableDataRecord(rowKey: string | number) {
    if (!dataSourceRef.value || dataSourceRef.value.length == 0) return;

    const rowKeyName = unref(getRowKey);
    if (!rowKeyName) return;

    const { childrenColumnName = 'children' } = unref(propsRef);

    const findRow = (array: any[]) => {
      let ret;
      array.some(function iter(r) {
        if (typeof rowKeyName === 'function') {
          if ((rowKeyName(r) as string) === rowKey) {
            ret = r;
            return true;
          }
        } else {
          if (Reflect.has(r, rowKeyName) && r[rowKeyName] === rowKey) {
            ret = r;
            return true;
          }
        }
        return r[childrenColumnName] && r[childrenColumnName].some(iter);
      });
      return ret;
    };
    return findRow(dataSourceRef.value);
  }

  // 获取表格数据
  function getDataSource<T = Recordable>() {
    return getDataSourceRef.value as T[];
  }
  // 获取后端接口原始数据
  function getRawDataSource<T = Recordable>() {
    return rawDataSourceRef.value as T;
  }

  async function reload(opt?: FetchParams) {
    return fetch(opt);
  }

  onMounted(() => {
    useTimeoutFn(() => {
      unref(propsRef).immediate && fetch();
    }, 16);
  });

  return {
    getDataSourceRef,
    getDataSource,
    getRawDataSource,
    getRowKey,
    setTableData,
    getAutoCreateKey,
    fetch,
    reload,
    updateTableData,
    deleteSelectRowByKey,
    insertTableDataRecord,
    updateTableDataRecord,
  };
}
